﻿//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//   Copyright(c) 2023, Hexagon's Asset Lifecycle Intelligence.All rights reserved.

//   ProgID: SEIDDP,Ingr.SP3D.SEIDDP.DIS02
//   Author:  Yuanpeng Zhang
//   Creation Date:     2023-03-06
//   Description: DIS02

//   Change History:
//   version        data              who                change description
//   =======        ===========       ==============     ==========================================================================================
//   2.0.0.2        2023-03-24        Yuanpeng Zhang     VB -> .net
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
using System;
using System.IO;
using System.Collections.ObjectModel;
using Ingr.SP3D.Common.Middle;
using Ingr.SP3D.Common.Middle.Services;
using Ingr.SP3D.Common.Exceptions;
using Ingr.SP3D.CommonSymbolFunctions;
using Ingr.SP3D.ReferenceData.Middle;
using System.Windows.Forms;
using Ingr.SP3D.Equipment.Middle;

namespace Ingr.SP3D.SEIDDP
{
    [CacheOption(CacheOptionType.NonCached)]
    [VariableOutputs]
    [SymbolVersion("2.0.0.2")]
    public class DIS02 : CustomSymbolDefinition //继承后者的类
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public DIS02() : base()
        {
            //有多少个port，就会重复进来多少次
            //这个dll就类似于pid的datasource对象           
            string DllPath = MiddleServiceProvider.SiteMgr.ActiveSite.ActivePlant.PlantCatalog.SymbolShare + @"\Custom Symbols\CommonSymbolFunctions.dll";
            if (File.Exists(DllPath) == false)
            {
                throw new Exception(@"SharedContent\Custom Symbols\CommonSymbolFunctions.dll 未找到，symbol无法工作");
            }
            else
            {
                Ingr.SP3D.Content.CommonSymbolFunctionLoader.Load();
            }
            defaultPartDataBasis = 15;
        }

        //DefinitionName/ProgID of this symbol is SEIDDP,Ingr.SP3D.SEIDDP.DIS02
        SymbolGeometryHelper oGemHelper = new SymbolGeometryHelper();
        double parD2, parInsulationThickness, parD3, parD4, parD5, parD6, parD7, parD8, parD9, parD10;
        int defaultPartDataBasis;
        double parPortIndex3, parPortIndex2, parPortIndex1, parNpd3, parNpd2, parNpd1;
        int parEndPreparation1, parScheduleThickness1, parEndStandard1, parPressureRating1, parFlowDirection1,
            parEndPreparation2, parScheduleThickness2, parEndStandard2, parPressureRating2, parFlowDirection2,
            parEndPreparation3, parScheduleThickness3, parEndStandard3, parPressureRating3, parFlowDirection3;
        string parNpdUnitType1, parId1, parNpdUnitType2, parId2, parNpdUnitType3, parId3;

        #region "Definition of Inputs" 
        //这个1 2 3 4代表了唯一的序号，先后顺序。因为所有的输入参数被视为一个集合
        //名字要和bulkload表里的属性名字一致。顺序、描述其实无所谓,外部的参数会根据Name自动匹配到对应的某一个参数中。
        [InputCatalogPart(1)]
        //默认这个是1
        public InputCatalogPart m_oPartDef;
        [InputDouble(2, "FacetoFace", "Face to Face", 1, true)]
        public InputDouble m_D2;
        [InputDouble(3, "InstrumentHeight3", "InstrumentHeight3", 0.5)]
        public InputDouble m_D3;
        [InputDouble(4, "InstrumentHeight4", "InstrumentHeight4", 0.2)]
        public InputDouble m_D4;
        [InputDouble(5, "InstrumentHeight5", "InstrumentHeight5", 0.5, true)]
        public InputDouble m_D5;
        [InputDouble(6, "InstrumentHeight6", "InstrumentHeight6", 0.5, true)]
        public InputDouble m_D6;
        [InputDouble(7, "InsulationThickness", "InsulationThickness", 0.025, true)]
        public InputDouble m_InsulationThickness;


        [InputDouble(8, "Npd", "Npd", 100, true)]
        public InputDouble m_Npd;
        [InputDouble(9, "EndPreparation", "End Preparation", 21, true)]
        public InputDouble m_EndPreparation;
        [InputDouble(10, "ScheduleThickness", "Schedule Thickness", 100, true)]
        public InputDouble m_ScheduleThickness;
        [InputDouble(11, "EndStandard", "End Standard", 5, true)]
        public InputDouble m_EndStandard;
        [InputDouble(12, "PressureRating", "Pressure Rating", 35, true)]
        public InputDouble m_PressureRating;
        [InputDouble(13, "FlowDirection", "Flow Direction", 3, true)]
        public InputDouble m_FlowDirection;
        [InputString(14, "NpdUnitType", "Npd Unit Type", "mm", true)]
        public InputString m_NpdUnitType;

        //port的话  9个一组
        [InputDouble(15, "PortIndex1", "Port Index 1", 1, true)]
        public InputDouble m_PortIndex1;
        [InputDouble(16, "Npd1", "Npd 1", 0, true)]
        public InputDouble m_Npd1;
        [InputDouble(17, "EndPreparation1", "End Preparation 1", 0, true)]
        public InputDouble m_EndPreparation1;
        [InputDouble(18, "ScheduleThickness1", "Schedule Thickness 1", 0, true)]
        public InputDouble m_ScheduleThickness1;
        [InputDouble(19, "EndStandard1", "End Standard 1", 0, true)]
        public InputDouble m_EndStandard1;
        [InputDouble(20, "PressureRating1", "Pressure Rating 1", 0, true)]
        public InputDouble m_PressureRating1;
        [InputDouble(21, "FlowDirection1", "Flow Direction 1", 0, true)]
        public InputDouble m_FlowDirection1;
        [InputString(22, "Id1", "Id 1", "VNoz1", true)]
        public InputString m_Id1;
        [InputString(23, "NpdUnitType1", "Npd Unit Type 1", "", true)]
        public InputString m_NpdUnitType1;


        [InputDouble(24, "PortIndex2", "Port Index 2", 2, true)]
        public InputDouble m_PortIndex2;
        [InputDouble(25, "Npd2", "Npd 2", 0, true)]
        public InputDouble m_Npd2;
        [InputDouble(26, "EndPreparation2", "End Preparation 2", 0, true)]
        public InputDouble m_EndPreparation2;
        [InputDouble(27, "ScheduleThickness2", "Schedule Thickness 2", 0, true)]
        public InputDouble m_ScheduleThickness2;
        [InputDouble(28, "EndStandard2", "End Standard 2", 0, true)]
        public InputDouble m_EndStandard2;
        [InputDouble(29, "PressureRating2", "Pressure Rating 2", 0, true)]
        public InputDouble m_PressureRating2;
        [InputDouble(30, "FlowDirection2", "Flow Direction 2", 0, true)]
        public InputDouble m_FlowDirection2;
        [InputString(31, "Id2", "Id 2", "VNoz2", true)]
        public InputString m_Id2;
        [InputString(32, "NpdUnitType2", "Npd Unit Type 2", "", true)]
        public InputString m_NpdUnitType2;


        [InputDouble(33, "PortIndex3", "Port Index 3", 3, true)]
        public InputDouble m_PortIndex3;
        [InputDouble(34, "Npd3", "Npd 3", 0, true)]
        public InputDouble m_Npd3;
        [InputDouble(35, "EndPreparation3", "End Preparation 3", 0, true)]
        public InputDouble m_EndPreparation3;
        [InputDouble(36, "ScheduleThickness3", "Schedule Thickness 3", 0, true)]
        public InputDouble m_ScheduleThickness3;
        [InputDouble(37, "EndStandard3", "End Standard 3", 0, true)]
        public InputDouble m_EndStandard3;
        [InputDouble(38, "PressureRating3", "Pressure Rating 3", 0, true)]
        public InputDouble m_PressureRating3;
        [InputDouble(39, "FlowDirection3", "Flow Direction 3", 0, true)]
        public InputDouble m_FlowDirection3;
        [InputString(40, "Id3", "Id 3", "VNoz3", true)]
        public InputString m_Id3;
        [InputString(41, "NpdUnitType3", "Npd Unit Type 3", "", true)]
        public InputString m_NpdUnitType3;

        [InputDouble(42, "InstrumentHeight7", "InstrumentHeight7", 0.1, true)]
        public InputDouble m_D7;
        [InputDouble(43, "InstrumentHeight8", "InstrumentHeight8", 0.5, true)]
        public InputDouble m_D8;
        [InputDouble(44, "InstrumentHeight9", "InstrumentHeight9", 0.5, true)]
        public InputDouble m_D9;
        [InputDouble(45, "ActuatorRotation1", "ActuatorRotation1", 0, true)]
        public InputDouble m_D10;

        #endregion

        #region "Definitions of Aspects and their Outputs"
        //名字要在实际outputs.add时，匹配上
        [Aspect("Physical", "Physical", AspectID.SimplePhysical)]
        [SymbolOutput("Flange1", "Flange1")]
        [SymbolOutput("Flange2", "Flange2")]
        [SymbolOutput("Cy1", "Cy1")]
        [SymbolOutput("Cy2", "Cy2")]
        [SymbolOutput("Cy3", "Cy3")]
        [SymbolOutput("Cy4", "Cy4")]
        [SymbolOutput("Cy5", "Cy5")]
        [SymbolOutput("Cy6", "Cy6")]
        [SymbolOutput("Cy7", "Cy7")]
        [SymbolOutput("Box1", "Box1")]
        [SymbolOutput("PNoz1", "Nozzle with out Length")]
        [SymbolOutput("PNoz2", "Nozzle with out Length")]
        [SymbolOutput("PNoz3", "Nozzle with out Length")]
        [SymbolOutput("PNoz4", "Nozzle with out Length")]
        public AspectDefinition m_Physical;  //Aspect可以理解为SymbolOutput的集合

        [Aspect("Insulation", "Insulation", AspectID.Insulation)]
        [SymbolOutput("InsulationBody", "Insulation Body")]
        public AspectDefinition m_Insulation;

        #endregion

        #region "Construct Outputs"

        /// <summary>
        /// 造型
        /// </summary>
        protected override void ConstructOutputs()
        {
            try
            {
                parD2 = m_D2.Value;
                parInsulationThickness = m_InsulationThickness.Value;
                parD3 = m_D3.Value;
                parD4 = m_D4.Value;
                parD5 = m_D5.Value;
                parD6 = m_D6.Value;
                parD7 = m_D7.Value;
                parD8 = m_D8.Value;
                parD9 = m_D9.Value;
                parD10 = m_D10.Value;
                // 角度会自动变为弧度进来
                // 长度会自动变为m为单位进来

                var TEST = m_FlowDirection.Value;
                //一组里
                parPortIndex1 = m_PortIndex1.Value;
                parNpd1 = m_Npd1.Value;
                parEndPreparation1 = (int)m_EndPreparation1.Value;
                parScheduleThickness1 = (int)m_ScheduleThickness1.Value;
                parEndStandard1 = (int)m_EndStandard1.Value;
                parPressureRating1 = (int)m_PressureRating1.Value;
                parFlowDirection1 = (int)m_FlowDirection1.Value;
                parId1 = m_Id1.Value;
                parNpdUnitType1 = m_NpdUnitType1.Value;

                parPortIndex2 = m_PortIndex2.Value;
                parNpd2 = m_Npd2.Value;
                parEndPreparation2 = (int)m_EndPreparation2.Value;
                parScheduleThickness2 = (int)m_ScheduleThickness2.Value;
                parEndStandard2 = (int)m_EndStandard2.Value;
                parPressureRating2 = (int)m_PressureRating2.Value;
                parFlowDirection2 = (int)m_FlowDirection2.Value;
                parId2 = m_Id2.Value;
                parNpdUnitType2 = m_NpdUnitType2.Value;

                parPortIndex3 = m_PortIndex3.Value;
                parNpd3 = m_Npd3.Value;
                parEndPreparation3 = (int)m_EndPreparation3.Value;
                parScheduleThickness3 = 1; //(int)m_ScheduleThickness3.Value;
                parEndStandard3 = (int)m_EndStandard3.Value;
                parPressureRating3 = (int)m_PressureRating3.Value;
                parFlowDirection3 = (int)m_FlowDirection3.Value;
                parId3 = m_Id3.Value;
                parNpdUnitType3 = m_NpdUnitType3.Value;

                PipeComponent DDP = (PipeComponent)m_oPartDef.Value;  //Get the part from the catalog
                SP3DConnection connection = this.OccurrenceConnection;
                //var partDataBasis = DDP.GetPropertyValue("IJDPipeComponent", "PartDataBasis");//如果要取part上的某个属性，可以这样。和spf很像

                RunPDBDIS02(DDP, connection, oGemHelper);


            }
            catch (Exception ex) // General Unhandled exception
            {
                throw (ex);
            }
        }

        #endregion

        #region "Geometry Construction"
        /// <summary>
        /// 最初的模板，该函数是根据不同的partDataBasis的值，来进行不同的处理
        /// </summary>
        /// <param name="DDP"></param>
        /// <param name="connection"></param>
        private void RunPDBDIS02(PipeComponent DDP, SP3DConnection connection, SymbolGeometryHelper oGemHelper)
        {
            try
            {
                if (parEndPreparation3 == 301)
                {
                    parPressureRating3 = 1;
                }
            }
            catch
            {

            }

            try
            {
                // UtilityFunctions.CheckParameterForZeroValues(this, "FacetoFace");

                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD2, 0))
                {
                    MessageBox.Show("D2不能<=0");
                    throw new Exception("D2不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD8, 0))
                {
                    MessageBox.Show("D8不能<=0");
                    throw new Exception("D8不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD5, 0))
                {
                    MessageBox.Show("D5不能<=0");
                    throw new Exception("D5不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD6, 0))
                {
                    MessageBox.Show("D6不能<=0");
                    throw new Exception("D6不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD9, 0))
                {
                    MessageBox.Show("D9不能<=0");
                    throw new Exception("D9不能<=0");
                }


                double BodySize = 0.2;
                double NPD1, NPD3, b, c, d, e;


                // 第 1 个port
                // DDP 或者说 动态参数的情况，都要用这种方式先创建出port，而不能用下面这个
                // PipeNozzle port2 = PortHelper.CreatePipeNozzle(pipeComponent, connection, false, 2, new Position(0, D2, 0), new Vector(-1, 0, 0), true, true);
                PipeNozzle port1 = PortHelper.CreateDynamicPipePort(connection, 1, parNpd1, parNpdUnitType1, parEndPreparation1, parScheduleThickness1, parEndStandard1, parPressureRating1, parFlowDirection1, parId1,
                                                                    defaultPartDataBasis, false, new Position(0, parD2, 0), new Vector(-1, 0, 0), true, true);
                port1.Length = 0.0001;
                m_Physical.Outputs.Add("PNoz1", port1);  //Nozzle1
                UtilityFunctions.GetPipingPortData(DDP, port1, out NPD1, out b, out c, out d, out e, true);

                // 第 2 个port
                PipeNozzle port2 = PortHelper.CreateDynamicPipePort(connection, 2, parNpd2, parNpdUnitType2, parEndPreparation2, parScheduleThickness2, parEndStandard2, parPressureRating2, parFlowDirection2, parId2,
                                                                    defaultPartDataBasis, false, new Position(parD5, 0, 0), new Vector(0, -1, 0), true, true);
                port2.Length = 0.0001;
                m_Physical.Outputs.Add("PNoz2", port2);

                //// 第 3 个port
                //PipeNozzle port3 = PortHelper.CreateDynamicPipePort(connection, 3, parNpd3, parNpdUnitType3, parEndPreparation3, parScheduleThickness3, parEndStandard3, parPressureRating3, parFlowDirection3, parId3, defaultPartDataBasis, false, new Position(parD5, 0, 0), new Vector(0, -1, 0), true, true);
                //m_Physical.Outputs.Add("PNoz3", port3);

                //// 第 4 个port
                //PipeNozzle port4 = PortHelper.CreateDynamicPipePort(connection, 4, parNpd4, parNpdUnitType4, parEndPreparation4, parScheduleThickness4, parEndStandard4, parPressureRating4, parFlowDirection4, parId4, defaultPartDataBasis, false, new Position(parD5, -parD9, 0), new Vector(0, -1, 0), true, true);
                //m_Physical.Outputs.Add("PNoz4", port4);
                //上述创建Port后，可以拿到port具体的一些值
                Double coneBaseRad, coneTopRad;
                if (parD5 > 0.04)
                {
                    coneBaseRad = 0.04;
                    coneTopRad = 0.03;
                }
                else
                {
                    coneBaseRad = 0.2 * parD5;
                    coneTopRad = 0.15 * parD5;
                }
                //CP1口shang面的圆台
                Position startPoint = new Position(parD5, 0.2 * parD2, 0);
                Position endPoint = new Position(parD5, 0, 0);
                var Conebody = Graphics3D.CreateCone(startPoint, endPoint, coneBaseRad, coneTopRad, true);
                m_Physical.Outputs.Add("Cy1", Conebody);

                //CP1 CP2中间的圆柱 
                startPoint = new Position(parD5, 0.2 * parD2, 0);
                endPoint = new Position(parD5, parD2 + 0.7 * parD6, 0);
                var Cylinderbody = Graphics3D.CreateCylinder(startPoint, endPoint, 2 * coneBaseRad, true);
                m_Physical.Outputs.Add("Cy2", Cylinderbody);


                //CP2口上面的圆台 
                startPoint = new Position(parD5, parD2 + 0.7 * parD6, 0);
                endPoint = new Position(parD5, parD2 + parD6, 0);
                Conebody = Graphics3D.CreateCone(startPoint, endPoint, coneBaseRad, coneTopRad, true);
                m_Physical.Outputs.Add("Cy3", Conebody);

                //突起的圆柱
                startPoint = new Position(parD5, parD2 + 0.3 * parD6, 0);
                endPoint = new Position(parD5, parD2 + 0.5 * parD6, 0);
                Cylinderbody = Graphics3D.CreateCylinder(startPoint, endPoint, 2.4 * coneBaseRad, true);
                m_Physical.Outputs.Add("Cy4", Cylinderbody);

                //突起的杆子
                startPoint = new Position(parD5, parD2 + 0.6 * parD6, 0);
                endPoint = new Position(parD5 + parD7 * Math.Sin(parD10), parD2 + 0.6 * parD6, -parD7 * Math.Cos(parD10));
                Cylinderbody = Graphics3D.CreateCylinder(startPoint, endPoint, 0.01, true);
                m_Physical.Outputs.Add("Cy5", Cylinderbody);

                //突起的杆子4
                startPoint = new Position(0, parD2, 0);
                endPoint = new Position(parD5, parD2, 0);
                Cylinderbody = Graphics3D.CreateCylinder(startPoint, endPoint, 0.05, true);
                m_Physical.Outputs.Add("Cy6", Cylinderbody);

                //突起的杆子2
                startPoint = new Position(parD5 + parD7 * Math.Sin(parD10), parD2 + 0.6 * parD6, -parD7 * Math.Cos(parD10));
                endPoint = new Position(parD5 + parD7 * Math.Sin(parD10) + parD8 * Math.Cos(parD10), parD2 + 0.6 * parD6, -parD7 * Math.Cos(parD10) + parD8 * Math.Sin(parD10));
                Cylinderbody = Graphics3D.CreateCylinder(startPoint, endPoint, 0.01, true);
                m_Physical.Outputs.Add("Cy7", Cylinderbody);


                //第 9 个，方块
                double BoxLength;
                if (parD7 < 0)
                {
                    BoxLength = (parD4 + parD7) * 2;
                }
                else
                {
                    BoxLength = (parD4 - parD7) * 2;
                }
                if (BoxLength > 0)
                {
                    oGemHelper.ActivePosition = new Position(endPoint.X, endPoint.Y, endPoint.Z);
                    oGemHelper.SetOrientation(new Vector(-Math.Cos(parD10), 0, -Math.Sin(parD10)), new Vector(0, 1, 0));
                    var Boxbody = oGemHelper.CreateBox(connection, BoxLength, BoxLength, BoxLength);
                    m_Physical.Outputs.Add("Box1", Boxbody);
                }
                else
                {
                    MessageBox.Show("D4 应大于 D7");
                }
                //保温层
                double maxDiameter = ReturnMax4(port1.PipingOutsideDiameter * 2, port2.PipingOutsideDiameter * 2, port1.FlangeOrHubOutsideDiameter, port2.FlangeOrHubOutsideDiameter);
                double InsulationDia = maxDiameter + 2 * parInsulationThickness;
                startPoint = new Position(-parD4 * 0.5 - parD3, 0, 0);
                endPoint = new Position(parD2 - parD3 - parD4 * 0.5, 0, 0);
                Cylinderbody = Graphics3D.CreateCylinder(startPoint, endPoint, InsulationDia, true);
                m_Insulation.Outputs.Add("InsulationBody", Cylinderbody);

            }
            catch (Exception ex) // General Unhandled exception
            {
                throw ex;
            }
        }
        public Double ReturnMax4(Double A, Double B, Double C, Double D)
        {
            Double MaxValue = A;
            if (MaxValue < B) { MaxValue = B; }
            if (MaxValue < C) { MaxValue = C; }
            if (MaxValue < D) { MaxValue = D; }
            return MaxValue;
        }


        #endregion

    }
}
